package com.yinhai.ta404.core.utils;

import com.yinhai.ta404.core.exception.AppException;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


public class FileTypesUtil {
    private static final Map<String, String> FILE_TYPE_MAP = new HashMap<>(64);

    static {
        initFileType();
    }

    private FileTypesUtil() {
    }


    private static void initFileType() {
        FILE_TYPE_MAP.put("jpg,JPG", "FFD8FF");
        FILE_TYPE_MAP.put("png,PNG", "89504E");
        FILE_TYPE_MAP.put("gif,GIF", "474946");
        FILE_TYPE_MAP.put("tif", "49492A");
        FILE_TYPE_MAP.put("bmp", "424D");
        FILE_TYPE_MAP.put("dwg", "414331");
        FILE_TYPE_MAP.put("html,htm", "3C21");
        FILE_TYPE_MAP.put("css", "48544D");
        FILE_TYPE_MAP.put("js", "696B2E");
        FILE_TYPE_MAP.put("rtf", "7B5C72");
        FILE_TYPE_MAP.put("psd,PSD", "384250");
        FILE_TYPE_MAP.put("EML", "46726F");
        FILE_TYPE_MAP.put("eml", "44656C");
        FILE_TYPE_MAP.put("doc,dot,xls,xlt,xla,ppt,apr,ppa,pps,pot,msi,sdw,db", "D0CF11");

        FILE_TYPE_MAP.put("ps", "252150");
        FILE_TYPE_MAP.put("pdf,fdf,PDF", "255044");
        FILE_TYPE_MAP.put("rmvb,rm", "2E524D");
        FILE_TYPE_MAP.put("flv,FLV", "464C56");
        FILE_TYPE_MAP.put("mp4,m4a", "000000");
        FILE_TYPE_MAP.put("mp3,MP3", "494433");
        FILE_TYPE_MAP.put("flac", "664c61");
        FILE_TYPE_MAP.put("mpg,MPA", "000001");
        FILE_TYPE_MAP.put("asf,wma,wmv,WMV", "3026B2");
        FILE_TYPE_MAP.put("wav,avi", "524946");

        FILE_TYPE_MAP.put("mid,midi,MID,MIDI", "4D5468");
        FILE_TYPE_MAP.put("jar,zip,docx,xlsx,pptx", "504B03");
        FILE_TYPE_MAP.put("rar,RAR", "526172");
        FILE_TYPE_MAP.put("ini", "235468");
        FILE_TYPE_MAP.put("exe,com,386,ax,acm,sys,dll,drv,flt,fon,ocx,scr,lrc,vxd,cpl,x32,vbx,EXE,DLL,OCX,OLB,IMM,IME", "4D5A");
        FILE_TYPE_MAP.put("jsp", "3C2540");
        FILE_TYPE_MAP.put("mf", "4D616E");
        FILE_TYPE_MAP.put("xml,XML", "3C3F78");
        FILE_TYPE_MAP.put("sql", "EFBBBF");
        FILE_TYPE_MAP.put("java", "706163");
        FILE_TYPE_MAP.put("bat", "406563");
        FILE_TYPE_MAP.put("gz,tar,tgz", "1F8B");
        FILE_TYPE_MAP.put("properties", "6C6F67");
        FILE_TYPE_MAP.put("class", "CAFEBA");
        FILE_TYPE_MAP.put("chm,chi,CHM,CHI", "495453");
        FILE_TYPE_MAP.put("mxp", "040000");
        FILE_TYPE_MAP.put("torrent", "643130");
        FILE_TYPE_MAP.put("264", "494D4B");
        FILE_TYPE_MAP.put("mov", "6D6F6");
        FILE_TYPE_MAP.put("wpd", "FF5750");
        FILE_TYPE_MAP.put("dbx", "CFAD12");
        FILE_TYPE_MAP.put("pst", "214244");
        FILE_TYPE_MAP.put("qdf", "AC9EBD");
        FILE_TYPE_MAP.put("pwl", "E38285");
        FILE_TYPE_MAP.put("ram", "2E7261");
        FILE_TYPE_MAP.put("raq", "525151");
    }



    public static String getFileTypeBySuffix(String fileName) {
        if (StringUtils.isEmpty(fileName)) {
            return null;
        }
        if (!fileName.contains(".")) {
            return null;
        }

        return fileName.substring(fileName.lastIndexOf('.') + 1);
    }


    public static String getImageFileType(File file) {
        if (isImage(file)) {
            try (ImageInputStream iis = ImageIO.createImageInputStream(file)) {
                Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
                if (!iter.hasNext()) {
                    return null;
                }
                ImageReader reader = iter.next();
                return reader.getFormatName();
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }


    public static String[] getFileTypeByFile(File file) {
        String[] fileType;
        byte[] b = new byte[50];
        try (FileInputStream is = new FileInputStream(file)) {
            is.read(b, 0, 50);
            fileType = getFileTypeByStream(b);
        } catch (IOException e) {
            throw new AppException("无法获取文件类型！");
        }
        return fileType;
    }


    public static String[] getFileTypeByStream(byte[] bytes) {
        String fileTypeHex = String.valueOf(getFileHexString(bytes));
        for (Map.Entry<String, String> entry : FILE_TYPE_MAP.entrySet()) {
            String fileTypeHexValue = entry.getValue();
            if (fileTypeHex.toUpperCase().startsWith(fileTypeHexValue)) {
                return entry.getKey().split(",");
            }
        }
        return new String[]{};
    }


    public static boolean isImage(File file) {
        boolean flag;
        try {
            BufferedImage bufReader = ImageIO.read(file);
            int width = bufReader.getWidth();
            int height = bufReader.getHeight();
            flag = width != 0 && height != 0;
        } catch (Exception e) {
            flag = false;
        }
        return flag;
    }


    public static boolean isImage(InputStream inputStream) {
        boolean flag;
        try {
            BufferedImage bufReader = ImageIO.read(inputStream);
            int width = bufReader.getWidth();
            int height = bufReader.getHeight();
            flag = width != 0 && height != 0;
        } catch (Exception e) {
            flag = false;
        }
        return flag;
    }


    private static String getFileHexString(byte[] bytes) {
        StringBuilder stringBuilder = new StringBuilder();
        if (bytes == null || bytes.length <= 0) {
            return null;
        }
        for (byte aByte : bytes) {
            int v = aByte & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

}
